
<!doctype html>
<html lang="en">
<head>
	<title>CS870 Computer Graphics Project : Alpha</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link rel=stylesheet href="css/base.css"/>
</head>
<body>

	<!-- setup information dialog -->
	<div id="infoButton"></div>
	<div id="infoBox" title="CS870 - Computer Graphics Project">
<pre>
Simon Mebrahtu Ogbamichael <smt725@unh.edu>
Computer Science Department, CEPS
University of New Hampshire

Dec 02, 2013

Project : WebGL Alpha
</pre>

<p>
N.B. Since the project is based on WebGL, in order for the code to run it needs to 
be hosted on a web server. I have uploaded the project to my google codes page, you 
can check it on this link:<br/>

 	<a href="http://simonica-webgl.googlecode.com/hg/index.html">
 		http://simonica-webgl.googlecode.com/hg/index.html
 	</a>

<br/>I hope it will save you from the trouble of having to host the files in some web server.
</P>

<ol>
	<li>Brief scene description:
		<ul>
			<li>a simple cube</li>
			<li>check board textured floor</li>
			<li>textured blue sky as background</li>
			<li>statistics (FPS) on bottom left of page</li>
			<li>Information icon on top right of page (displays contents of this file)</li>
			<li>GUI controls panel on the top right side of the page</li>
		</ul>
	</li>
	<li>Facility to adjust the following properties of the cube:
		<ul>
			<li>position (x, y, z)</li>
			<li>color, opacity, material, visibility, and animation</li>
		</ul>
	</li>
	<li>Properties of perspective camera:
		<ul>
			<li>position (x, y, z)</li>
			<li>view angle, aspect ration, near, and far</li>
		</ul>
	</li>
	<li>Properties of scene:
		<ul>
			<li>draw axises</li>
			<li>draw floor</li>
			<li>floor texture repeat (x, y)</li>
			<li>floor texture attributes (wrapS, wrapT, MAG. MIN)</li>
			<li>and flipY</li>
		</ul>
	</li>
	<li>Light properties:
		<ul>
			<li>positon (x, y, z)</li>
			<li>enable/disable light</li>
		</ul>
	</li>
	<li>Shaders
		<ul>
			<li>enable/disable a simple colorify shader</li>
			<li>specify color for shader</li>
		</ul>
	</li>
	<li>Reset scene</li>
</ol>
	</div>

	<!-- this div element will host WebGL/HTML5 Canvas -->
	<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
</body>

<!-- main library - equivalent to glut -->
<script type='text/javascript' src="js/Three.js"></script>
<!-- detect if browser supprts WebGL, otherwise use HTML5 Canvas -->
<script type='text/javascript' src="js/Detector.js"></script>
<!-- How many frames per second? -->
<script type='text/javascript' src="js/Stats.js"></script>
<!-- Scene rotation -->
<script type='text/javascript' src="js/OrbitControls.js"></script>
<!-- Keyboard events -->
<script type='text/javascript' src="js/THREEx.KeyboardState.js"></script>
<!-- Fullscreen handler -->
<script type='text/javascript' src="js/THREEx.FullScreen.js"></script>
<!-- Window resize handler -->
<script type='text/javascript' src="js/THREEx.WindowResize.js"></script>
<!-- GUI library - equivalent to GLUI -->
<script type='text/javascript' src='js/dat.gui.min.js'></script>
<!-- GUI library - to display information button and the information dialog -->
<script type='text/javascript' src="js/jquery-1.9.1.js"></script>
<script type='text/javascript' src="js/jquery-ui.js"></script>
<script type='text/javascript' src="js/info.js"></script>
<link rel=stylesheet href="css/jquery-ui.css" />
<link rel=stylesheet href="css/info.css"/>

<!-- include shaders -->
<script type='text/javascript' src="js/EffectComposer.js"></script>
<script type='text/javascript' src="js/RenderPass.js"></script>
<script type='text/javascript' src="js/ShaderPass.js"></script>
<script type='text/javascript' src="js/MaskPass.js"></script> 
<script type='text/javascript' src="js/BloomPass.js"></script> 
<script type='text/javascript' src="js/CopyShader.js"></script>
<script type='text/javascript' src="js/ColorifyShader.js"></script>
<!-- include custom surface geometry -->
<script type='text/javascript' src="js/SurfaceGeometry.js"></script>

<!-- The real code begins here ... -->
<script>
// global variables
var container, scene, camera, light, renderer, controls, stats, floor, floorTexture;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();

// global variables
var cube, sweep;
var composer, shaderTime = 0;
var parameters, lightParameters, cameraParameters, sceneParameters,
	textureParameters, textureRepeat, geoParameters;
var gui;
var axis;
var renderPass, copyPass, colorifyPass;

var sin = Math.sin, cos = Math.cos, pi = Math.PI;

// default is sphere
var xUvExp = 'sin(u) * cos(v)',
	yUvExp = 'cos(u)',
	zUvExp = '-sin(u) * sin(v)';

var uSlices = 32, vStacks = 32, sscale = 20;
var xUvField, yUvField, zUvField, uSlicesField, vStacksField, sScaleField;

init();
initGUI();
animate();

function sphere(u, v) {
    var x = sin(u) * cos(v);
    var y = cos(u);
    var z = -sin(u) * sin(v);

    return new THREE.Vector3(x, y, z);
}

function presetSphere() {
    xUvField.setValue("sin(u) * cos(v)");
    yUvField.setValue("cos(u)");
    zUvField.setValue("-sin(u) * sin(v)");
    sScaleField.setValue(50);

    createGraph();
}

function torus(u, v){
    var x = cos(u)*(3 + 1*cos(v));
    var y = sin(u)*(3 + 1*cos(v));
    var z = 1*sin(v);

    return new THREE.Vector3(x, y, z);	
}

function presetTorus(){
    xUvField.setValue("cos(u)*(1 + 0.25*cos(v))");
    yUvField.setValue("sin(u)*(1 + 0.25*cos(v))");
    zUvField.setValue("0.25*sin(v)");
    sScaleField.setValue(50);

    createGraph();
}

function klein(u, v) {
    u = u * 2;
    var x, y, z;
    if (u < pi) {
        x = 3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(u) * cos(v);
        z = -8 * sin(u) - 2 * (1 - cos(u) / 2) * sin(u) * cos(v);
    } else {
        x = 3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(v + pi);
        z = -8 * sin(u);
    }
  
    y = -2 * (1 - cos(u) / 2) * sin(v);
    
    return new THREE.Vector3(x, y, z);
}

function presetKlein(){
    xUvField.setValue("3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(u) * cos(v)");
    yUvField.setValue("y = -2 * (1 - cos(u) / 2) * sin(v)");
    zUvField.setValue("-8 * sin(u) - 2 * (1 - cos(u) / 2) * sin(u) * cos(v)");
    sScaleField.setValue(10);

    createGraph();
}

function createGraph(){		
	var fun = new Function("u", "v", "return new THREE.Vector3(" + xUvExp + ", " + yUvExp + ", " + zUvExp + ");");

    var materials = [
        new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1 } )
    ];	

    if(sweep){
    	scene.remove(sweep);
    }

    sweep = THREE.SceneUtils.createMultiMaterialObject( new THREE.SurfaceGeometry( uSlices, vStacks, fun ), materials );
    sweep.children[ 0 ].doubleSided = true;
    sweep.position.set( 0, 150, 0 );
    sweep.scale.multiplyScalar(sscale);
    scene.add( sweep );	  
}

/**
 * Setup the GUI
 */
function initGUI(){
	// main gui handle
	gui = new dat.GUI();
	
	// cube parameters that enable to user to control some aspects of the scene and objects
	parameters = 
	{
		x: 0, y: 30, z: 0,		
		color: "#ff0000", // color (change "#" to "0x")
		opacity: 1, 		
		visible: true,
		animated: false,		
		material: "Phong",
		reset: function() { resetScene() }
	};

	// floor texture parameters
	textureParameters = 
	{
		wrapS: "RepeatWrapping",
		wrapT: "RepeatWrapping",
		magFilter: "LinearFiler",
		minFilter: "LinearMipMapLinearFilter",		
		flipY: false
	}

	textureRepeat = 
	{
		x: 10, y: 10
	}

	// light parameters
	lightParameters = 
	{
		x: -100, y: 150, z: 100,
		visible: true
	}

	// camera parameters
	cameraParameters = 
	{
		x: 0, y: 150, z: 400, 
		fov: 45, aspect: window.innerWidth / window.innerHeight, near: 0.1, far: 20000
	}

	// scene parameters
	sceneParameters = 
	{
		drawAxises: true,
		drawBackground: true
	}

	// parametric geometry parameters
	geoParameters = {		
		presetSphere: function() { presetSphere(); },
		presetTorus: function() { presetTorus(); },
		presetKlein: function() { presetKlein(); },
		createGraph: function() { createGraph(); }
	}

	// setup parametric folder
	var paraFolder = gui.addFolder('Parametric Geometry');

	var funcFolder = paraFolder.addFolder('func(u, v)');
	xUvField = funcFolder.add( this, 'xUvExp' ).name('x = f(u,v) = ');
	yUvField = funcFolder.add( this, 'yUvExp' ).name('y = g(u,v) = ');
	zUvField = funcFolder.add( this, 'zUvExp' ).name('z = h(u,v) = ');
	uSlicesField = funcFolder.add( this, 'uSlices' ).name('slices(u) = ');
	vStacksField = funcFolder.add( this, 'vStacks' ).name('stacks(v) = ');
	sScaleField = funcFolder.add( this, 'sscale' ).name('scale = ');

	funcFolder.open()

	var presetFolder = paraFolder.addFolder('Preset Equations');
	presetFolder.add( geoParameters, 'presetSphere' ).name('Sphere');
	presetFolder.add( geoParameters, 'presetTorus' ).name('Torus');
	presetFolder.add( geoParameters, 'presetKlein' ).name('Klein');
	presetFolder.open();

	paraFolder.add( geoParameters, 'createGraph' ).name("Create Graph");

	// setup cube folder
	var cubeFolder = gui.addFolder('Cube');

	// attach cube position folder
	var positionFolder = cubeFolder.addFolder('Position');

	// add cube position controls and attach event handlers
	var cubeX = positionFolder.add( parameters, 'x' ).min(-200).max(200).step(1).listen();
	var cubeY = positionFolder.add( parameters, 'y' ).min(0).max(100).step(1).listen();
	var cubeZ = positionFolder.add( parameters, 'z' ).min(-200).max(200).step(1).listen();
	cubeX.onChange(function(value){   
		cube.position.x = value;   
	});
	cubeY.onChange(function(value){   
		cube.position.y = value;   
	});
	cubeZ.onChange(function(value){   
		cube.position.z = value;   
	});
	positionFolder.open();

	// setup cube color control and attach event listener
	var cubeColor = cubeFolder.addColor( parameters, 'color' ).name('Color').listen();
	cubeColor.onChange(function(value){   
		cube.material.color.setHex( value.replace("#", "0x") );   
	});
	
	// setup cube opacity control and attach event listener
	var cubeOpacity = cubeFolder.add( parameters, 'opacity' ).min(0).max(1).step(0.01).name('Opacity').listen();
	cubeOpacity.onChange(function(value){   
		cube.material.opacity = value;   
	});

	// setup cube material control and attach event listener
	var cubeMaterial = cubeFolder.add( parameters, 'material', [ "Basic", "Lambert", "Phong", "Wireframe" ] ).name('Material').listen();
	cubeMaterial.onChange(function(value){   
		updateScene();   
	});
	
	// setup cube visiblity control and attach event listener
	var cubeVisible = cubeFolder.add( parameters, 'visible' ).name('Visible?').listen();
	cubeVisible.onChange(function(value){   
		cube.visible = value;  	
	});

	// setup cube animation control and attach event listener
	var cubeAnimated = cubeFolder.add( parameters, 'animated' ).name('Animate?').listen();
	cubeAnimated.onChange(function(value){   
		cube.animated = value;
	});		

	// setup camera properties folder
	var cameraFolder = gui.addFolder('Camera');

	// setup camera properties controls, attach event listeners, and add to folder
	var cameraFov = cameraFolder.add( cameraParameters, 'fov' ).min(0).max(90).step(1).name('View Angle').listen();
	var cameraAspect = cameraFolder.add( cameraParameters, 'aspect' ).min(0).max(5).step(1).name('Aspect Ratio').listen();
	var cameranear = cameraFolder.add( cameraParameters, 'near' ).min(0).max(100).step(1).name('near').listen();
	var camerafar = cameraFolder.add( cameraParameters, 'far' ).min(0).max(20000).step(100).name('far').listen();
	cameraFov.onChange(function(value){ 
		camera.fov = value;  
	});		
	cameraAspect.onChange(function(value){ 
		camera.aspect = value;  
	});	
	cameranear.onChange(function(value){ 
		camera.near = value;  
	});	
	camerafar.onChange(function(value){ 
		camera.far = value;  
	});				

	// setup camera position properties folder
	var cameraPosition = cameraFolder.addFolder('Position');

	// setup camera position properties controls, attach event listeners, and add them to folder
	var cameraX = cameraPosition.add( cameraParameters, 'x' ).min(-500).max(500).step(1).listen();
	var cameraY = cameraPosition.add( cameraParameters, 'y' ).min(-500).max(500).step(1).listen();
	var cameraZ = cameraPosition.add( cameraParameters, 'z' ).min(-500).max(500).step(1).listen();	
	cameraX.onChange(function(value){   
		camera.position.x = value;   
	});
	cameraY.onChange(function(value){   
		camera.position.y = value;   
	});
	cameraZ.onChange(function(value){   
		camera.position.z = value;   
	});	
	cameraPosition.open();

	// setup scene properties folder
	var sceneFolder = gui.addFolder('Scene');	
	var drawAxises = sceneFolder.add( sceneParameters, 'drawAxises').name('Draw Axises').listen();
	drawAxises.onChange(function(value){
		axis.visible = value;
	});

	// setup floor properties folder and attach to scene folder
	var floorFolder = sceneFolder.addFolder('Floor');	
	var drawBackground = floorFolder.add( sceneParameters, 'drawBackground').name('Draw Floor').listen();
	drawBackground.onChange(function(value){
		floor.visible = value;
	});

	// setup floor texture properties folder and attach to floor folder
	var textureFolder = floorFolder.addFolder('Texture');

	// setup floor texture repeat properties folder and attach to floor texture folder
	var repeatFolder = textureFolder.addFolder('Repeat');

	// setup controls for floor texture repeat properties, attach event handlers and add them to folder
	var repeatX = repeatFolder.add( textureRepeat, 'x' ).min(0).max(20).step(1).listen();
	var repeatY = repeatFolder.add( textureRepeat, 'y' ).min(0).max(20).step(1).listen();
	repeatX.onChange(function(value){   
		floorTexture.repeat.x = value;   
		floorTexture.needsUpdate = true;
	});
	repeatY.onChange(function(value){   
		floorTexture.repeat.y = value;  
		floorTexture.needsUpdate = true; 
	});
	repeatFolder.open();

	// setup controls for floor texture properties, attach event handlers and add them to folder
	var wrapS = textureFolder.add( textureParameters, 'wrapS', [ "ClampToEdgeWrapping", "RepeatWrapping", "MirroredRepeatWrapping"] ).name('WrapS').listen();
	var wrapT = textureFolder.add( textureParameters, 'wrapT', [ "ClampToEdgeWrapping", "RepeatWrapping", "MirroredRepeatWrapping"] ).name('WrapT').listen();
	var magFilter = textureFolder.add( textureParameters, 'magFilter', [ "LinearFilter", "nearestFilter"] ).name('MAG').listen();		
	var minFilter = textureFolder.add( textureParameters, 'minFilter', [ "LinearMipMapLinearFilter", "nearestFilter", "nearestMipMapnearestFilter", "nearestMipMapLinearFilter", "LinearFilter", "LinearMipMapnearestFilter"] ).name('MIN').listen();		
	var flipY = textureFolder.add( textureParameters, 'flipY' ).name('FlipY?').listen();

	wrapS.onChange(function(value){   
		floorTexture.wrapS = THREE.RepeatWrapping;
		if(value == "ClampToEdgeWrapping"){
			floorTexture.wrapS = THREE.ClampToEdgeWrapping;						
		} else if(value == "MirroredRepeatWrapping"){
			floorTexture.wrapS = THREE.MirroredRepeatWrapping;			
		} 
		floorTexture.needsUpdate = true;
	});	
	wrapT.onChange(function(value){   
		floorTexture.wrapT = THREE.RepeatWrapping;
		if(value == "ClampToEdgeWrapping"){
			floorTexture.wrapT = THREE.ClampToEdgeWrapping;						
		} else if(value == "MirroredRepeatWrapping"){
			floorTexture.wrapT = THREE.MirroredRepeatWrapping;			
		} 
		floorTexture.needsUpdate = true;
	});	
	magFilter.onChange(function(value){   
		floorTexture.magFilter = THREE.LinearFilter;			
		if(value == "nearestFilter"){
			floorTexture.magFilter = THREE.nearestFilter;			
		}
		floorTexture.needsUpdate = true;
	});	
	minFilter.onChange(function(value){   
		floorTexture.minFilter = THREE.LinearMipMapLinearFilter;			
		if(value == "nearestFilter"){
			floorTexture.minFilter = THREE.nearestFilter;			
		} else if(value == "nearestMipMapnearestFilter"){
			floorTexture.minFilter = THREE.nearestMipMapnearestFilter;			
		} else if(value == "nearestMipMapLinearFilter"){
			floorTexture.minFilter = THREE.nearestMipMapLinearFilter;			
		} else if(value == "LinearFilter"){
			floorTexture.minFilter = THREE.LinearFilter;			
		} else if(value == "LinearMipMapnearestFilter"){
			floorTexture.minFilter = THREE.LinearMipMapnearestFilter;			
		} 
		floorTexture.needsUpdate = true;
	});
	flipY.onChange(function(value){   
		 floorTexture.flipY = value;
		 floorTexture.needsUpdate = true;  	
	});	
	textureFolder.open();	
	floorFolder.open();

	// setup light properties folder
	var lightFolder = gui.addFolder('Light');
	var lightVisible = lightFolder.add( lightParameters, 'visible' ).name('Enable?').listen();
	lightVisible.onChange(function(value){   
		light.visible = value;  	
	});

	// setup light position properties folder and attach it to light properties folder
	var lightPosition = lightFolder.addFolder('Position');

	// setup controls for light position properties, attach event handlers, and add them to folder
	var lightX = lightPosition.add( lightParameters, 'x' ).min(-200).max(200).step(1).listen();
	var lightY = lightPosition.add( lightParameters, 'y' ).min(-200).max(200).step(1).listen();
	var lightZ = lightPosition.add( lightParameters, 'z' ).min(-200).max(200).step(1).listen();	
	
	lightX.onChange(function(value){   
		light.position.x = value;   
	});
	lightY.onChange(function(value){   
		light.position.y = value;   
	});
	lightZ.onChange(function(value){   
		light.position.z = value;   
	});	
	lightPosition.open();

	// setup shader parameters
	shaderParameters = {
		colorify: false,	
		color: "#ff00ee",
	}	

	// setup shaders folder
	var shadersFolder = gui.addFolder('Shaders');
	shadersFolder.add(shaderParameters, 'colorify').name('Colorify').onChange(onToggleShaders);	
	// setup shader color control and attach event listener
	var shaderColor = shadersFolder.addColor( shaderParameters, 'color' ).name('Color').listen();
	shaderColor.onChange(function(value){      
		colorifyPass.uniforms[ "color" ].value = new THREE.Color( value );
	});	

	// add reset control 
	gui.add( parameters, 'reset' ).name("Reset Scene");
	
	// expand the top level of the GUI
	gui.open();	

	onToggleShaders();

	presetSphere();
}

/**
 * Shaders handler
 */
 function onToggleShaders() {

	composer = new THREE.EffectComposer( renderer);
	
	//Add Shader Passes to Composer

	composer.addPass( renderPass );
	
	if (shaderParameters.colorify){
		composer.addPass( colorifyPass );
	}

	composer.addPass( copyPass );
	//set last pass in composer chain to renderToScreen
	copyPass.renderToScreen = true;
}

/**
 * Initialize WebGL
 */
function init() 
{	

	// get the DOM element to attach to
	var $container = $('#ThreeJS');

	// Instialize scene
	scene = new THREE.Scene();

	// Setup camera
	var screen_width = window.innerWidth, screen_height = window.innerHeight;
	var view_angle = 65, aspect_ratio = screen_width / screen_height, near = 0.1, far = 20000;

	// aquire a perspective camera, set its position, and add it to scene
	camera = new THREE.PerspectiveCamera( view_angle, aspect_ratio, near, far);
	scene.add(camera);

	// camera starts at origin, so pull it back (z = 400)
	camera.position.set(0,150,400);
	camera.lookAt(scene.position);	

	// Setup renderer - prefer WebGL, fallback to HTML5 Canvas with older browsers
	// or browsers that does not support WebGL
	if (Detector.webgl){
		renderer = new THREE.WebGLRenderer({antialias:true});
	} else {
		renderer = new THREE.CanvasRenderer(); 	
	}
	renderer.setSize(screen_width, screen_height);

	// attach renderer with host(div) element
	$container.append(renderer.domElement);

	// Create Shader Passes
	renderPass = new THREE.RenderPass( scene, camera );
	copyPass = new THREE.ShaderPass( THREE.CopyShader );
	
	colorifyPass = new THREE.ShaderPass( THREE.ColorifyShader );
	colorifyPass.uniforms[ "color" ].value = new THREE.Color( "#4daf52" );


	// attach window resize and full screen handlers
	THREEx.WindowResize(renderer, camera);
	THREEx.FullScreen.bindKey({ charCode : 'f'.charCodeAt(0) });

	// attach camera rotation handler
	controls = new THREE.OrbitControls( camera, renderer.domElement );

	// setup statistics (FPS - frames per second)
	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.bottom = '0px';
	stats.domElement.style.zIndex = 100;
	$container.append( stats.domElement );

	// setup basic light
	light = new THREE.PointLight(0xffffff);
	light.position.set(-100,150,100);
	scene.add(light);

	// setup textured Floor
	floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
	floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; 
	floorTexture.repeat.set( 10, 10 );
	var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
	var floorGeometry = new THREE.PlaneGeometry(800, 1000, 10, 10);
	floor = new THREE.Mesh(floorGeometry, floorMaterial);
	floor.position.y = -0.5;
	floor.rotation.x = Math.PI / 2;
	scene.add(floor);

	// SKYBOX
	var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
	var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
	var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
	scene.add(skyBox);

	//Create sky texture
	var skyTexture = THREE.ImageUtils.loadTexture( "images/sky.jpeg" );
	var skyMaterial = new THREE.MeshBasicMaterial( { 
		map : skyTexture
	} );

	//create sky plane
	var geometry = new THREE.PlaneGeometry(1800*2, 1600,1,1);
	var sky = new THREE.Mesh(geometry, skyMaterial);
	sky.position.z = - 500;	
	//scene.add(sky);	
	
	// add objects to scene
	var cubeGeometry = new THREE.CubeGeometry( 50, 50, 50 );
	var cubeMaterial = new THREE.MeshPhongMaterial( { color:0xff0000, transparent:true, opacity:1 } );
	cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
	cube.position.set(0,25,0);
	scene.add(cube);

	// setup axis coordinates
	axis = new THREE.AxisHelper(200);
	scene.add(axis);
}

/**
 * Update the scene, called when some properies change
 */
function updateScene()
{
	// update material properties of the cube
	var value = parameters.material;
	var newMaterial;
	if (value == "Basic"){
		newMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
	} else if (value == "Lambert"){
		newMaterial = new THREE.MeshLambertMaterial( { color: 0x000000 } );
	} else if (value == "Phong"){
		newMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
	} else { // draw as Wireframe
		newMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
	}
	cube.material = newMaterial;
	cube.material.color.setHex( parameters.color.replace("#", "0x") );
	cube.material.opacity = parameters.opacity;  
	cube.material.transparent = true;
	
	// update position of the cube
	cube.position.x = parameters.x;
	cube.position.y = parameters.y;
	cube.position.z = parameters.z;

	// update other properties of the cube
	cube.animated = parameters.animated;
	cube.visible = parameters.visible;	

	// update light properties
	light.visible = lightParameters.visible;
	light.position.x = lightParameters.x;
	light.position.y = lightParameters.y;
	light.position.z = lightParameters.z;

	// update scene properties
	axis.visible = sceneParameters.drawAxises;
	floor.visible = sceneParameters.drawBackground;

	// update camera properties
	camera.fov = cameraParameters.fov;
	camera.aspect = cameraParameters.aspect;
	camera.near = cameraParameters.near;
	camera.far = cameraParameters.far;
	camera.position.x = cameraParameters.x;
	camera.position.y = cameraParameters.y;
	camera.position.z = cameraParameters.z;
}

/**
 * Reset the scene - reinitialize parameters and update the scene.
 */
function resetScene()
{
	initParameters();
	updateScene();
}

/**
 * Initialize all the parameters
 */
function initParameters(){
	// initialize cube parameters
	parameters.x = 0;
	parameters.y = 50;
	parameters.z = 0;
	parameters.color = "#ff0000";
	parameters.opacity = 1;
	parameters.visible = true;	
	parameters.animated = false;
	parameters.material = "Phong";

	// initialize scene parameters
	sceneParameters.drawAxises = true;	
	sceneParameters.drawBackground = true;		

	// initialize light parameters
	lightParameters.visible = true;
	lightParameters.x = -100;
	lightParameters.y = 150;
	lightParameters.z = 100;

	// initialize camera parameters
	cameraParameters.x = 0;
	cameraParameters.y = 150;
	cameraParameters.z = 400;
	cameraParameters.fov = 45;	
	cameraParameters.aspect = window.innerWidth / window.innerHeight;
	cameraParameters.near = 0.1;
	cameraParameters.far = 20000;

	// initialize floor texture parameters
	floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
	floorTexture.magFilter = THREE.LinearFilter;
	floorTexture.minFilter = THREE.LinearMipMapLinearFilter;
	floorTexture.flipY = false;
	floorTexture.needsUpdate = true;
}

/**
 * Update canvas
 */
function animate() 
{	
    requestAnimationFrame( animate );

	// update camera projection matrix
	camera.updateProjectionMatrix();

	composer.render( 0.1);		
	update();
}

/**
 * Update controls and handle keyboard and mouse events.
 */
function update()
{

	if (keyboard.pressed("z")) 
	{
		// do something
	}
	
	controls.update();
	stats.update();
}

/**
 * Real rendering of the scene happens here.
 */
function render() 
{
	    // animate cube
    if(cube.animated){
	    var timer = Date.now() * 0.0001;

	    camera.position.x = Math.cos( timer ) * 800;
	    camera.position.z = Math.sin( timer ) * 800;

	    camera.lookAt( scene.position );

	    for ( var i = 0, l = scene.children.length; i < l; i ++ ) {

	        var object = scene.children[ i ];

	        object.rotation.x += 0.01;
	        object.rotation.y += 0.005;

	    }		
	}


	renderer.render( scene, camera );
}

</script>
</html>
